#include "uiwindowimpl.h"

CUiWindowsImpl::CUiWindowsImpl(void)
{

}
CUiWindowsImpl::~CUiWindowsImpl(void)
{

}

//////////////////////////////////////////////////////////////////////////
std_method_type_impl(void*) CUiWindowsImpl::CreateUiWindow(void* hParentHwnd)
{
	CPaintManagerUI::SetInstance(GetInstance());
	CPaintManagerUI::SetResourcePath(m_strResFile.c_str());
	CWndShadow::Initialize(GetModuleHandle(NULL));
	this->Create(NULL, _T("ListDemo"), UI_WNDSTYLE_FRAME, WS_EX_STATICEDGE | WS_EX_APPWINDOW, 0, 0, 600, 320);
	this->CenterWindow();

	return NULL;
}
std_method_type_impl(int) CUiWindowsImpl::DestroyUiWindow()
{
	return S_SUCCESS;
}
std_method_type_impl(int) CUiWindowsImpl::AddUiWindow(void* hWnd)
{
	return S_SUCCESS;
}
std_method_type_impl(int) CUiWindowsImpl::ShowUiWindow(int nCmdShow)
{
	return S_SUCCESS;
}
std_method_type_impl(int) CUiWindowsImpl::SetResourceFile(LPSTRING file)
{
	m_file.clear();
	m_file.append(file);
	return S_SUCCESS;
}
std_method_type_impl(int) CUiWindowsImpl::SetResource(HINSTANCE instance, LPSTRING path)
{
	m_strResFile.clear();
	m_strResFile.append(path);
	m_strResFile.append(_T("//"));
	return S_SUCCESS;
}
std_method_type_impl(int) CUiWindowsImpl::SendMessage(const NotifyEvent* event)
{
	return S_SUCCESS;
}
std_method_type_impl(int) CUiWindowsImpl::PostMessage(const NotifyEvent* event)
{
	return S_SUCCESS;
}
std_method_type_impl(int) CUiWindowsImpl::TranslateMessage(const NotifyEvent* event)
{
	LRESULT lRes = 0;
	int rc = event->Window == m_pm.GetPaintWindow();
	rc_assert(rc != 0, S_ERROR)
	m_pm.PreMessageHandler(event->message, event->wParam, event->lParam, lRes);
	return S_SUCCESS;
}
std_method_impl CUiWindowsImpl::BindEvent(IBase* pEvents)
{
	HRESULT hr = S_OK;

	hr = pEvents->QueryInterface(IID_IUIEvent, (void**)&m_pEvent);
	rc_assert(hr == S_OK, E_FAIL)

	return S_OK;
}
std_method_impl CUiWindowsImpl::UnBindEvent()
{
	m_pEvent.dispose();
	return S_OK;
}
LPSTRING CUiWindowsImpl::GetWindowClassName() const {

	return _T("UIWindow");
};
UINT CUiWindowsImpl::GetClassStyle() const {

	return CS_DBLCLKS;
};

void CUiWindowsImpl::Notify(TNotifyUI& msg)
{
	if (msg.pSender == m_pCloseBtn)
	{
		::PostQuitMessage(0L);
	}
	else if (msg.sType == _T("selectchanged"))
	{
		m_pEvent->OnUiEvent(NULL);

		CDuiString name = msg.pSender->GetName();
		CTabLayoutUI* pControl = static_cast<CTabLayoutUI*>(m_pm.FindControl(_T("switch")));
		if (name == _T("st"))
			pControl->SelectItem(0);
		else if (name == _T("tf"))
			pControl->SelectItem(1);
		else if (name == _T("cv"))
			pControl->SelectItem(2);
	}
}

LRESULT CUiWindowsImpl::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	LONG styleValue = ::GetWindowLong(*this, GWL_STYLE);
	styleValue &= ~WS_CAPTION;
	::SetWindowLong(*this, GWL_STYLE, styleValue | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
	m_pm.Init(m_hWnd);

	basic_tstring strRes(m_strResFile);
	strRes += m_file;

	CDlgBuilder builder;
	CControlUI* pRoot = builder.Create(strRes.c_str(), (UINT)0, NULL, &m_pm);
	rc_assert_log(pRoot != NULL, 0, "Failed to parse XML")

	m_pm.AttachDialog(pRoot);
	m_pm.AddNotifier(this);

	m_pCloseBtn = static_cast<CButtonUI*>(m_pm.FindControl(_T("closebtn")));

	return 0;
}

LRESULT CUiWindowsImpl::OnClose(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	bHandled = FALSE;
	return 0;
}
LRESULT CUiWindowsImpl::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	::PostQuitMessage(0L);
	bHandled = FALSE;
	return 0;
}
LRESULT CUiWindowsImpl::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	SIZE szRoundCorner = m_pm.GetRoundCorner();
	if (!::IsIconic(*this) && (szRoundCorner.cx != 0 || szRoundCorner.cy != 0)) {
		CDuiRect rcWnd;
		::GetWindowRect(*this, &rcWnd);
		rcWnd.Offset(-rcWnd.left, -rcWnd.top);
		rcWnd.right++; rcWnd.bottom++;
		RECT rc = { rcWnd.left, rcWnd.top + szRoundCorner.cx, rcWnd.right, rcWnd.bottom };
		HRGN hRgn1 = ::CreateRectRgnIndirect(&rc);
		HRGN hRgn2 = ::CreateRoundRectRgn(rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom - szRoundCorner.cx, szRoundCorner.cx, szRoundCorner.cy);
		::CombineRgn(hRgn1, hRgn1, hRgn2, RGN_OR);
		::SetWindowRgn(*this, hRgn1, TRUE);
		::DeleteObject(hRgn1);
		::DeleteObject(hRgn2);
	}

	bHandled = FALSE;
	return 0;
}

LRESULT CUiWindowsImpl::OnNcHitTest(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	POINT pt; 

	pt.x = GET_X_LPARAM(lParam); 
	pt.y = GET_Y_LPARAM(lParam);
	::ScreenToClient(*this, &pt);

	RECT rcClient;
	::GetClientRect(*this, &rcClient);

	RECT rcCaption = m_pm.GetCaptionRect();
	if (pt.x >= rcClient.left + rcCaption.left && pt.x < rcClient.right - rcCaption.right \
		&& pt.y >= rcCaption.top && pt.y < rcCaption.bottom) 
	{
		CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(pt));
		if (pControl && _tcscmp(pControl->GetClass(), DUI_CTR_BUTTON) != 0 &&
			_tcscmp(pControl->GetClass(), DUI_CTR_OPTION) != 0 &&
			_tcscmp(pControl->GetClass(), DUI_CTR_TEXT) != 0)
			return HTCAPTION;
	}

	return HTCLIENT;
}

LRESULT CUiWindowsImpl::OnGetMinMaxInfo(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	MONITORINFO oMonitor = {};
	oMonitor.cbSize = sizeof(oMonitor);
	::GetMonitorInfo(::MonitorFromWindow(*this, MONITOR_DEFAULTTOPRIMARY), &oMonitor);
	CDuiRect rcWork = oMonitor.rcWork;
	rcWork.Offset(-oMonitor.rcMonitor.left, -oMonitor.rcMonitor.top);

	LPMINMAXINFO lpMMI = (LPMINMAXINFO)lParam;
	lpMMI->ptMaxPosition.x = rcWork.left;
	lpMMI->ptMaxPosition.y = rcWork.top;
	lpMMI->ptMaxSize.x = rcWork.right;
	lpMMI->ptMaxSize.y = rcWork.bottom;

	bHandled = FALSE;
	return 0;
}
LRESULT CUiWindowsImpl::OnSysCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	if (wParam == SC_CLOSE) {
		::PostQuitMessage(0L);
		bHandled = TRUE;
		return 0;
	}
	BOOL bZoomed = ::IsZoomed(*this);
	LRESULT lRes = CWindowWnd::HandleMessage(uMsg, wParam, lParam);
	if (::IsZoomed(*this) != bZoomed) {
		if (!bZoomed) {
			CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
			if (pControl) pControl->SetVisible(false);
			pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
			if (pControl) pControl->SetVisible(true);
		}
		else {
			CControlUI* pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("maxbtn")));
			if (pControl) pControl->SetVisible(true);
			pControl = static_cast<CControlUI*>(m_pm.FindControl(_T("restorebtn")));
			if (pControl) pControl->SetVisible(false);
		}
	}
	return lRes;
}
LRESULT CUiWindowsImpl::OnNcActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	if (::IsIconic(*this)) 
		bHandled = FALSE;

	return (wParam == 0) ? TRUE : FALSE;
}
LRESULT CUiWindowsImpl::OnNcCalcSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	return 0;
}
LRESULT CUiWindowsImpl::OnNcPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	return 0;
}
LRESULT CUiWindowsImpl::OnKeyDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	return 0;
}
LRESULT CUiWindowsImpl::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	LRESULT lRes = 0;
	BOOL bHandled = TRUE;

	switch (uMsg) {
	case WM_CREATE:        
		lRes = OnCreate(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_CLOSE:         
		lRes = OnClose(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_SIZE:          
		lRes = OnSize(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_NCHITTEST:     
		lRes = OnNcHitTest(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_SYSCOMMAND:    
		lRes = OnSysCommand(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_GETMINMAXINFO: 
		lRes = OnGetMinMaxInfo(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_NCACTIVATE:    
		lRes = OnNcActivate(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_DESTROY:     
		lRes = OnDestroy(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_NCCALCSIZE: //you must ~~~~~~~
		lRes = OnNcCalcSize(uMsg, wParam, lParam, bHandled);
		break;
	case WM_NCPAINT:       
		lRes = OnNcPaint(uMsg, wParam, lParam, bHandled); 
		break;
	case WM_KEYDOWN:       
		lRes = OnKeyDown(uMsg, wParam, lParam, bHandled); 
		break;
	default:
		bHandled = FALSE;
	}

	if (bHandled)
		return lRes;

	if (m_pm.MessageHandler(uMsg, wParam, lParam, lRes))
		return lRes;

	return CWindowWnd::HandleMessage(uMsg, wParam, lParam);
}

